#include "externtypes.h"
#include <iostream>
#include <cmath>

using namespace std;


Grey_Image* pixbuftoGrey(Glib::RefPtr<Gdk::Pixbuf>* img){
    Grey_Image* out;
    out = new Grey_Image((*img)->get_height(),(*img)->get_width(),(unsigned int)pow(2.0,(int)(*img)->get_bits_per_sample()));

    unsigned int **pixelmap = out->pixelmap;

    unsigned char *pixel,*pixel_aux;
    int bitesfactor,bitesperpixel;
    unsigned int aux;

    pixel=(*img)->get_pixels();

    switch((*img)->get_bits_per_sample()){
        case 8:
            bitesfactor = 1;
            bitesperpixel=bitesfactor*(*img)->get_n_channels();
            for(int i=0;i<(*img)->get_height();i++)
                for(int j=0;j<(*img)->get_width();j++){
                    pixel_aux=pixel + i*(*img)->get_rowstride() + bitesperpixel*j;
                    pixelmap[i][j]= *pixel_aux;
                }
            break;
        case 16:
            bitesfactor = 2;
            bitesperpixel=bitesfactor*(*img)->get_n_channels();
            for(int i=0;i<(*img)->get_height();i++)
                for(int j=0;j<(*img)->get_width();j++){
                    pixel_aux=pixel + i*(*img)->get_rowstride() + bitesperpixel*j;
                    aux=*pixel_aux;
                    aux=aux*512;
                    pixel_aux++;
                    pixelmap[i][j] = aux + *pixel_aux;
                }

            break;
        default:
            //Error: Too much bits per pixel
            break;
    }

    return out;
}

Color_Image* pixbuftoColor(Glib::RefPtr<Gdk::Pixbuf>* img){

    Color_Image* out;
    out = new Color_Image((*img)->get_height(),(*img)->get_width());

    ColorPixel **pixelmap = out->pixelmap;

    unsigned char *pixel,*pixel_aux;
    int bitesfactor,bitesperpixel;

    pixel=(*img)->get_pixels();

    switch((*img)->get_bits_per_sample()){
        case 8:
            bitesfactor = 1;
            bitesperpixel=bitesfactor*(*img)->get_n_channels();
            for(int i=0;i<(*img)->get_height();i++)
                for(int j=0;j<(*img)->get_width();j++){
                    pixel_aux=pixel+i*(*img)->get_rowstride() + bitesperpixel*j;
                    pixelmap[i][j]=ColorPixel(*pixel_aux,*(pixel_aux+1),*(pixel_aux+2));
                }
            break;
        default:
            //Error: Too much bits per pixel
            break;
    }
    return out;
}

Glib::RefPtr<Gdk::Pixbuf>* greytoPixbuf(Grey_Image* img){
    Glib::RefPtr<Gdk::Pixbuf>* out= new Glib::RefPtr<Gdk::Pixbuf>;

    *out = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,false,8,img->getWidth(),img->getHeight());

    unsigned char* data=(*out)->get_pixels();

    unsigned char *pixel_aux;
    int bitesfactor,bitesperpixel;

    switch((*out)->get_bits_per_sample()){
        case 8:
            bitesfactor = 1;
            bitesperpixel=bitesfactor*(*out)->get_n_channels();
            for(int i=0;i<(*out)->get_height();i++)
                for(int j=0;j<(*out)->get_width();j++){
                    pixel_aux=data+i*(*out)->get_rowstride() + bitesperpixel*j;
                    unsigned char a = (unsigned char)(((float)256/img->getGreyLevels())*img->getPixel(j,i));
                    *pixel_aux=a;
                    (*(pixel_aux+1))=a;
                    (*(pixel_aux+2))=a;
                }
            break;
        default:
            //Error: Too much bits per pixel
            break;
    }

    return out;
}

Glib::RefPtr<Gdk::Pixbuf>* binarytoPixbuf(Binary_Image* img){
     Glib::RefPtr<Gdk::Pixbuf>* out= new Glib::RefPtr<Gdk::Pixbuf>;

    *out = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,false,8,img->getWidth(),img->getHeight());

    unsigned char* data=(*out)->get_pixels();

    unsigned char *pixel_aux;
    int bitesfactor,bitesperpixel;

    switch((*out)->get_bits_per_sample()){
        case 8:
            bitesfactor = 1;
            bitesperpixel=bitesfactor*(*out)->get_n_channels();
            for(int i=0;i<(*out)->get_height();i++)
                for(int j=0;j<(*out)->get_width();j++){
                    pixel_aux=data+i*(*out)->get_rowstride() + bitesperpixel*j;
                    *pixel_aux=255*(int)img->getPixel(j,i);
                    (*(pixel_aux+1))=255*(int)img->getPixel(j,i);
                    (*(pixel_aux+2))=255*(int)img->getPixel(j,i);
                }
            break;
        default:
            //Error: Too much bits per pixel
            break;
    }

    return out;
}

Glib::RefPtr<Gdk::Pixbuf>* colortoPixbuf(Color_Image* img){
    Glib::RefPtr<Gdk::Pixbuf>* out= new Glib::RefPtr<Gdk::Pixbuf>;


    *out = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,false,8,img->getWidth(),img->getHeight());

    unsigned char* data=(*out)->get_pixels();

    unsigned char *pixel_aux;
    int bitesfactor,bitesperpixel;

    switch((*out)->get_bits_per_sample()){
        case 8:
            bitesfactor = 1;
            bitesperpixel=bitesfactor*(*out)->get_n_channels();
            for(int i=0;i<(*out)->get_height();i++)
                for(int j=0;j<(*out)->get_width();j++){
                    pixel_aux=data+i*(*out)->get_rowstride() + bitesperpixel*j;
                    *pixel_aux=img->getPixel(j,i).getRed();
                    (*(pixel_aux+1))=img->getPixel(j,i).getGreen();
                    (*(pixel_aux+2))=img->getPixel(j,i).getBlue();
                }
            break;
        default:
            //Error: Too much bits per pixel
            break;
    }

    return out;
}


Glib::RefPtr<Gdk::Pixbuf>* imagetoPixbuf(Image* img){
    switch(img->getType()){
        case Image::BINARY:
            return binarytoPixbuf((Binary_Image*)img);
            break;
        case Image::GREY:
            return greytoPixbuf((Grey_Image*)img);
            break;
        case Image::COLOR:
            return colortoPixbuf((Color_Image*)img);
            break;
        default:
            return NULL;
            break;
    }
}
